package gui;

import java.util.ArrayList;
import java.util.List;

import building.Cell;
import building.InfoAgent;
import building.InfoGame;

public class Statistics {

	private int savedCiv, turnsToFinish;
	private boolean gameFinished;
	private InfoGame game;
	GraphicInterface gui;


	/**********************/
	private int[] ev_floor; // civili evacuati per piano
	private List<InfoAgent> agents; // lista degli infoagent corrispondenti ai
									// civili evacuati
	private int civilian_panic;
	private int civilian_injured;
	private double environmentBonus;
	private int green;
	private int yellow;
	private int orange;
	private int red;
	private int[] died;
	private int[] injured;
	private int[] civilian_ofFloor_evac; // i civili appartenenti al floor che
	private int totCivInFloor;
											// sono evacuati.

	/*********************
	 * /** Number of Civilian evacuated civilian evacuated for floor Percent of
	 * healthy turns needed to evacuation number of movements for each agent
	 * 
	 * @param game
	 * @param gui
	 */
	public Statistics(InfoGame game, GraphicInterface gui) {
		this.gui = gui;
		this.game = game;
		gameFinished = false;
		savedCiv = 0;

		turnsToFinish = -1;
		this.ev_floor = new int[2];
		this.died = new int[2];
		this.injured = new int[2];
		this.agents = new ArrayList<InfoAgent>(20);

		this.civilian_panic = 0;
		this.civilian_injured = 0;
		// TODO pensar com fer això
		// discoveredBuildings=findDiscoveredBuildings(game);
		this.civilian_ofFloor_evac = new int[2];
		totCivInFloor = game.getInfo().getNumCivillians()
				+ game.getInfo().getNumEvacuators();
		System.out.println("Tot Civ in floor " + totCivInFloor);

	}

	public void incMovement(InfoAgent a) {
		int aux;
		aux = a.getMovements();
		a.setMovements(aux + 1);
		a.setLastTurn(game.getInfo().getTurn());
	}

	public void scoreSaved() {
		if (!gameFinished)
			if (isFinished()) {
				gameFinished = true;
				turnsToFinish = game.getInfo().getTurn();
			}
	}

	public int getSavedCiv() {
		return savedCiv;
	}

	public void setTurnsToFinish(int turnsToFinish) {
		this.turnsToFinish = turnsToFinish;
	}

	public int getTurnsToFinish() {
		return turnsToFinish;
	}

	/**
	 * A message is shown in the log area of the GUI
	 * 
	 * @param str
	 *            String to show
	 */
	private void showMessage(String str) {
		if (gui != null)
			gui.showLog(str + "\n");
		System.out.println(str);
	}

	/****************************/

	public void show() {
		gui.showStatistics("");
		gui.showStatistics("Simulation Finished");
		gui.showStatistics("*******************");
		gui.showStatistics("");
		gui.showStatistics("Civilian evacuated: " + savedCiv + " on "
				+ (totCivInFloor * 2));
		gui.showStatistics(numb_ev_4floor());
		gui.showStatistics(createHealtStatistics());

		gui.showStatistics("Turns to finish: " + turnsToFinish);
		for (int f = 0; f < agents.size(); f++) {
			gui.showStatistics("Agent " + agents.get(f).getAID().getLocalName()
					+ "  tooks a : " + agents.get(f).getMovements()
					+ " second to go  " + (agents.get(f).getMovements() * 1.50)
					+ " meters.");

		}
		performanceMesureEnvironment();
		float performanceTot = 0;
		for (int i = 0; i < game.getNfloors(); i++) {
			performanceTot += ev_performance(i);
		}

		performanceTot = performanceTot / 2;

		gui.showStatistics("Performance totale = " + performanceTot);

		gui.showStatistics("");
		gui.showStatistics("*******************");

	}

	/** Caterina *****************************/

	public void incEvac4floor(int floor) {
		this.ev_floor[floor]++;
		System.err.println("ev_floor " + floor + ev_floor[floor]);

	}

	public void civEv() {
		this.savedCiv++;
	}

	public void addAgents(InfoAgent ag) {
		this.agents.add(ag);
		System.err.println("ag.getMyFloor " + ag.getMyFloor());
		// this.civilian_ofFloor_evac[ag.getMyFloor()]++;
		// this.civilian_ofFloor_evac[ag
		// .getMyFloor()] + 1;

	}

	public String numb_ev_4floor() {
		return " Evacuation for floor: 0 " + countCivOfFloorSaved(0)
				+ " civilian" + "\n floor: 1 " + countCivOfFloorSaved(1)
				+ " civilian ";
	}

	public int countCivOfFloorSaved(int floor) {
		int count = 0;
		for (int i = 0; i < agents.size(); i++) {
			if (agents.get(i).getMyFloor() == floor) {
				count++;
			}
		}
		return count;

	}

	public String createHealtStatistics() {

		String s = null;

		for (int i = 0; i < agents.size(); i++) {
			float h = agents.get(i).getHealty();
			if (h >= 80)
				green++;
			if (h >= 60 && h < 80)
				yellow++;
			if (h >= 40 && h < 60)
				orange++;
			if (h >= 20 && h < 40)
				red++;

		}

		/*
		 * for (int f = 0; f < game.getMap().nfloor; f++) {
		 * 
		 * for (int x = 0; x < game.getMap().length; x++) { for (int y = 0; y <
		 * game.getMap().width; y++) { Cell c = game.getCell(x, y, f); try { if
		 * (c.isThereAnAgent()) {
		 * 
		 * if (c.getAgent().died || c.getAgent().healthy < 20 ||
		 * c.getAgent().imBlocked( c.getAgent().getAID(), game)) { died[f] =
		 * died[f]++; System.out.println("died floor " + f + died[f]); } if
		 * (c.getAgent().injured) { injured[f] = injured[f]++; }
		 * 
		 * 
		 * }
		 * 
		 * } catch (Exception e) { // Rarely will go here } } } }
		 */

		if (savedCiv > 0) {
			s = "Civilian with level healt > 80% " + green + "\n"
					+ " with level healt = 60% " + yellow + "\n"
					+ " with level healt = 40% " + orange + "\n"
					+ " with level healt = 20% " + red + "\n"
					// + " blocked or died or injured " + died + "\n"
					+ " Civilian in panic_stiken =  " + civilian_panic + "\n"
					+ " injured civilian =  " + civilian_injured + "\n";
		} else {
			s = "Civilian in the building are died :(";
		}

		return s;

	}

	public boolean allDied() {
		List<InfoAgent> agentInGame = new ArrayList<InfoAgent>();
		for (int f = 0; f < game.getMap().nfloor; f++) {
			for (int x = 0; x < game.getMap().length; x++) {
				for (int y = 0; y < game.getMap().width; y++) {
					Cell c = game.getCell(x, y, f);
					try {
						if (c.isThereAnAgent())
							agentInGame.add(c.getAgent());

					} catch (Exception e) {
						// Rarely will go here
					}
				}
			}
		}

		if (agentInGame.isEmpty()) {
			return false;
		} else {
			for (InfoAgent infoAgent : agentInGame) {
				if (infoAgent != null && !infoAgent.died) {
					return false;
				}
			}
			return true;
		}
	}

	public boolean isFinished() {

		if (allDied()) {
			System.out.print("stats: all dead");
			return true;
		}
		for (int f = 0; f < game.getMap().nfloor; f++) {
			for (int x = 0; x < game.getMap().length; x++) {
				for (int y = 0; y < game.getMap().width; y++) {
					Cell c = game.getCell(x, y, f);
					try {
						if (c.isThereAnAgent()) {
							System.out.println("agent is still on floor"
									+ c.getAgent());
							InfoAgent ia = c.getAgent();
							if ((ia.getAgentType() == InfoAgent.EVACUATOR || ia
									.getAgentType() == InfoAgent.CIVILIAN)
									&& !ia.injured
									&& ia.panic != 80
									&& !ia.died)
								return false;
						}

					} catch (Exception e) {
						// Rarely will go here
					}
				}
			}
		}
		this.game.getInfo().setGameFinished(true);
		System.err.println("**************   GAME FINISHED");

		return true;

	}

	public int getCivilian_panic() {
		return civilian_panic;
	}

	public void setCivilian_panic() {

		this.civilian_panic++;
		System.err.println("civilian panic " + this.civilian_panic);
	}

	public int getCivilian_injured() {
		return civilian_injured;
	}

	public void setCivilian_injured(int num) {
		this.civilian_injured = num;
		System.err.println("civilian panic " + this.civilian_injured);
	}

	public void performanceMesureEnvironment() {
		int num_celle = (game.getMap().width * game.getMap().length) * 2;
		double perc_ostacoli = (game.getNumOstacles() / num_celle) / 100;
		double perc_firePoints = (countFirePoints() / num_celle) / 100;
		double perc_turn = ((float) game.getInfo().getTurn() / num_celle) / 100;
		System.out.println("per_ostacoli " + perc_ostacoli + " perc_fireP "
				+ perc_firePoints + " perc_turn " + perc_turn);
		environmentBonus = perc_ostacoli + perc_firePoints + perc_turn;
		// gui.showStatistics("performance measure " + environmentBonus);

	}

	public double ev_performance(int floor) {

		int agentSavedPerFloor = countCivOfFloorSaved(floor);

																// dal floor
		System.out.println("agentSavedPerFloor by countCivOfFloorSaved  floor "
				+ floor + " "
				+ agentSavedPerFloor); // (evacuator
																		// compreso)

		double ev_turns = ((float) getEvacuatorTurn(floor) / this.turnsToFinish) / 100;

		float diedXfloor = totCivInFloor - agentSavedPerFloor;

		System.out.println("diedXfloor " + floor + " =" + diedXfloor);
		// System.out.println("injured x floor " + floor + " " +
		// injured[floor]);
		double perc_died = (double) ((float) diedXfloor * 0.1);
		System.out.println("perc_died " + floor + " " + perc_died);
		// double perc_inj = (double) ((float) injured[floor] * 0.005);
		// System.out.println("perc_inju " + floor + " " + perc_inj);
		double perc_saved = ((float) agentSavedPerFloor / (game.getInfo()
				.getNumCivillians() + game.getInfo().getNumEvacuators()))
				+ perc_died;

		gui.showStatistics("evacuator piano " + floor + "  = "
				+ (perc_saved + ev_turns + environmentBonus));


		return perc_saved + ev_turns + environmentBonus;
	}
	

	
	
	private int getEvacuatorTurn(int floor) {

		for (int i = 0; i < agents.size(); i++) {
			InfoAgent ag = agents.get(i);
			if (ag.getMyFloor() == floor
					&& ag.getAgentType() == InfoAgent.EVACUATOR) {
				System.out.println("Get Evacuatro Turn " + ag.getMovements());
				return ag.getMovements();
			}
		}

		return 0;
	}

	public float countFirePoints() {
		float countF = 0;
	
		for (int f = 0; f < game.getMap().nfloor; f++) {
			for (int x = 0; x < game.getMap().length; x++) {
				for (int y = 0; y < game.getMap().width; y++) {
					Cell c = game.getCell(x, y, f);
						if (c.getCellType() == Cell.FIRE) 
							countF++;
						
		
					}
			}
		}
		System.out.println("countFirePoints " + countF);
		return countF;
	}
}
/******************************************/
